/**
 *
 */
package vn.smartware.co.framework.swt.base;

import java.awt.BorderLayout;
import java.lang.reflect.Constructor;
import java.util.ArrayList;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CCombo;
import org.eclipse.swt.custom.CLabel;
import org.eclipse.swt.custom.CTabFolder;
import org.eclipse.swt.custom.CTabFolder2Adapter;
import org.eclipse.swt.custom.CTabFolderEvent;
import org.eclipse.swt.custom.CTabItem;
import org.eclipse.swt.custom.ScrolledComposite;
import org.eclipse.swt.events.KeyAdapter;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseTrackAdapter;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.ShellAdapter;
import org.eclipse.swt.events.ShellEvent;
import org.eclipse.swt.events.TraverseEvent;
import org.eclipse.swt.events.TraverseListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.ExpandBar;
import org.eclipse.swt.widgets.ExpandItem;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.ProgressBar;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.TabFolder;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.Text;
import org.eclipse.wb.swt.SWTResourceManager;

import vn.smartware.co.framework.action.Requester;
import vn.smartware.co.framework.bean.MenuDTO;
import vn.smartware.co.framework.bean.ProgramDTO;
import vn.smartware.co.framework.bean.LoginDTO;
import vn.smartware.co.framework.common.BaseConstant;
import vn.smartware.co.framework.exception.ClientException;
import vn.smartware.co.framework.exception.FatalException;
import vn.smartware.co.framework.exception.SessionTimeOutException;
import vn.smartware.co.framework.form.BaseForm;
import vn.smartware.co.framework.form.LoginForm;
import vn.smartware.co.framework.plugin.LangResources;
import vn.smartware.co.framework.swt.components.DigitalClock;
import vn.smartware.co.framework.utils.MsgBoxUtils;

/**
 * SWTBase
 * @author thuctt
 */
@SuppressWarnings("rawtypes")
public class SWTBase {

	private static Log log = LogFactory.getLog(SWTBase.class);
	
	private CLabel clblLine2;
	
	private ExpandBar bar;

	private Composite cmpOnScrollComposite;

	private Composite comp_LEFT;

	private CLabel clblUser;

	private Button btnExit;

	private Button btnLogin;

	private static final Rectangle resolution = Display.getCurrent().getBounds();

	private Shell shellP;

	private Shell splash;

	private CTabFolder tabFolder;

	/**
	 * MENUOPEN = 0
	 */
	public static final int MENUOPEN = 0;

	/**
	 * BUSINESSOPEN = 1
	 */
	public static final int BUSINESSOPEN = 1;

	private ExpandItem[] bars;
	
	/**
	 * SHELL_SIZE_X = 1024
	 */
	private static final int SHELL_SIZE_X = 1024;

	/**
	 * SHELL_SIZE_Y = 768
	 */
	private static final int SHELL_SIZE_Y = 735;

	/**
	 * COMPOSITE_SIZE_X = 800
	 */
	public static final int COMPOSITE_SIZE_X = 812;

	/**
	 * COMPOSITE_SIZE_Y = 725
	 */
	public static final int COMPOSITE_SIZE_Y = 703;//736;

	/**
	 * Constructor
	 * @param display
	 */
	public SWTBase (Display display){
		
		try {
			
			initShell(display);
			
			createContents();

			SWTManager.getInstance().setBaseManager(this);
			
			if (!shellP.isDisposed()) {
				
				openSplashWindow();

				shellP.open();
				shellP.layout();
				
				closeSplashWindow();
				
				btnLogin.setFocus();
			}
			
			while (!shellP.isDisposed()) {
				if (!display.readAndDispatch())
					display.sleep();
			}
			
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * init Shell
	 * @param display 
	 *
	 */
	private void initShell(Display display) {

//		ImageData ideaData = new ImageData(getClass().getResourceAsStream(BaseConstant.IMG_SYSTEM_ICON));
//		int whitePixel = ideaData.palette.getPixel(new RGB(255, 255, 255));
//		ideaData.transparentPixel = whitePixel;
//		final Image transparentIdeaImage = new Image(display, ideaData);

		shellP = new Shell(display, SWT.MIN | SWT.CLOSE | SWT.TITLE);
		shellP.setText(LangResources.getText("SWTBase.app_name"));
		shellP.setSize(SHELL_SIZE_X, SHELL_SIZE_Y);
		int startX = (resolution.width - SHELL_SIZE_X) / 2;
//		int startY = (resolution.height - SHELL_SIZE_Y) / 2;
		int startY = 0;
		shellP.setLocation(startX, startY);
//		shellP.setImage(transparentIdeaImage);
		shellP.setImage(SWTResourceManager.getImage(SWTBase.class, BaseConstant.IMG_SYSTEM_ICON));
		shellP.addListener(SWT.Traverse, new Listener() {
		    public void handleEvent(Event e) {
		        if (e.detail == SWT.TRAVERSE_ESCAPE) {
		            e.doit = false;
		            exitAction(true);
		        }
		    }
		});
		shellP.addShellListener(new ShellAdapter(){
			public void shellClosed(ShellEvent e) {
				e.doit = false;
				exitAction(true);
			}
		});
		
//		Canvas canvas = new Canvas(shellP, SWT.NONE);
//		canvas.addPaintListener(new PaintListener() {
//			public void paintControl(PaintEvent e) {
//				e.gc.drawImage(transparentIdeaImage, 0, 0);
//			}
//		});
	}

	/**
	 * createContents
	 */
	protected void createContents() {

		comp_LEFT = new Composite(shellP, SWT.BORDER);
		comp_LEFT.setLocation(0,0);
		comp_LEFT.setSize(200, shellP.getSize().y);
		comp_LEFT.setBackground(BaseConstant.COLOR_BGR_BASE);
		
		final Label lblImage = new Label(comp_LEFT, SWT.NONE);
		lblImage.setBounds(0, 0, 197, 59);
		lblImage.setImage(SWTResourceManager.getImage(SWTBase.class, BaseConstant.IMG_SYSTEM_LOGO));
		
		clblUser = new CLabel(comp_LEFT, SWT.SHADOW_IN | SWT.CENTER | SWT.BORDER);
		clblUser.setBounds(0, 60,196, 22);
		clblUser.setForeground(SWTResourceManager.getColor(0, 0, 255));
		clblUser.setFont(BaseConstant.FONT_BOLD_LABEL);
		
		btnLogin = new Button(comp_LEFT, SWT.NONE);
		btnLogin.setBounds(2, 85, 100, 25);
		btnLogin.setFont(BaseConstant.FONT_BASE_BUTTON);
		btnLogin.setText(LangResources.getText("SWTBase.btnLogin"));
		btnLogin.setCursor(SWTResourceManager.getCursor(SWT.CURSOR_HAND));
		btnLogin.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(final SelectionEvent arg0) {
				reloginAction();
			}
		});
		
		btnExit = new Button(comp_LEFT, SWT.NONE);
		btnExit.setBounds(104, 85, 90, 25);
		btnExit.setFont(BaseConstant.FONT_BASE_BUTTON);
		btnExit.setCursor(SWTResourceManager.getCursor(SWT.CURSOR_HAND));
		btnExit.setText(LangResources.getText("SWTBase.btnExit"));
		btnExit.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(final SelectionEvent arg0) {
				exitAction(true);
			}
		});
		
		final CLabel clblLine1 = new CLabel(comp_LEFT, SWT.SHADOW_OUT | SWT.CENTER | SWT.BORDER);
		clblLine1.setBounds(0, 111, 200, 3);
		clblLine1.setBackground(SWTResourceManager.getColor(0, 128, 255));
		
		final DigitalClock clock = new DigitalClock(comp_LEFT, SWT.NONE, new Point(196, 26), null, null, null);
		clock.setBounds(0, 112, 196, 26);
		clock.start();
		
		final ScrolledComposite scrollComposite = new ScrolledComposite(shellP, SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL);
		scrollComposite.setLocation(202, 0);
		scrollComposite.setSize(this.shellP.getSize().x-208, this.shellP.getSize().y-28);
		scrollComposite.setBackground(SWTResourceManager.getColor(100, 100, 50));
		
		cmpOnScrollComposite = new Composite(scrollComposite, SWT.NONE);
		cmpOnScrollComposite.setLayoutData(new BorderLayout(0, 0));
		cmpOnScrollComposite.setLocation(0, 0);
		cmpOnScrollComposite.setSize(scrollComposite.getSize().x-4, scrollComposite.getSize().y-4);
		
		tabFolder = new CTabFolder(cmpOnScrollComposite, SWT.CLOSE | SWT.FLAT | SWT.BORDER);
		tabFolder.addTraverseListener(new TraverseListener() {
			public void keyTraversed(final TraverseEvent e) {
				if (e.detail == SWT.TRAVERSE_ESCAPE) {
		            e.doit = false;
		            closeAction();
		        }
			}
		});
		tabFolder.addCTabFolder2Listener(new CTabFolder2Adapter() {
			public void close(final CTabFolderEvent event) {
				if (!closeAction()){
					event.doit = false;
				}
			}
		});
		tabFolder.setLocation(0, 0);
		tabFolder.setSize(cmpOnScrollComposite.getSize());
		tabFolder.setTabHeight(23);
		tabFolder.setSimple(false);
		tabFolder.setFont(SWTResourceManager.getFont("Microsoft Sans Serif", 10, SWT.BOLD));
		tabFolder.setBackground(SWTResourceManager.getColor(245, 250, 220));
		tabFolder.setSelectionBackground(new Color[] {Display.getCurrent().getSystemColor(SWT.COLOR_CYAN),
													  Display.getCurrent().getSystemColor(SWT.COLOR_BLUE) },
										 new int[] { 100 }, 
										 true);
		tabFolder.setForeground(SWTResourceManager.getColor(160, 160, 160));
		tabFolder.setSelectionForeground(Display.getCurrent().getSystemColor(SWT.COLOR_WHITE));
		tabFolder.setUnselectedCloseVisible(false);
		
		scrollComposite.setContent(cmpOnScrollComposite);
		
		shellP.setDefaultButton(btnLogin);
		
		clblLine2 = new CLabel(comp_LEFT, SWT.SHADOW_OUT | SWT.CENTER | SWT.BORDER);
		clblLine2.setBounds(0, 138, 200, 3);
		clblLine2.setBackground(SWTResourceManager.getColor(0, 128, 255));
		
		SWTManager.getInstance().setBaseManager(this);
		SWTManager.getInstance().setTabFolder(tabFolder);
	}

	/**
	 * openSplashWindow
	 */
	private void openSplashWindow() throws FatalException {

		try {
			splash = new Shell(SWT.ON_TOP);
			splash.setLayout(new GridLayout(1, false));
			Label splashLabel = new Label(splash, SWT.NONE);
			splashLabel.setImage(SWTResourceManager.getImage(SWTBase.class, BaseConstant.IMG_SPLASH));
	
			ProgressBar progressBar = new ProgressBar (splash, SWT.SMOOTH);
			GridData gd = new GridData(GridData.FILL_HORIZONTAL);
			progressBar.setLayoutData(gd);
			
			Label loadLabel = new Label(splash, SWT.NONE);
			GridData gd1 = new GridData(GridData.FILL_HORIZONTAL);
			loadLabel.setLayoutData(gd1);
	
			splash.pack();
	
			//
			Rectangle shellRect = splash.getBounds();
			int x = (resolution.width - shellRect.width) / 2;
			int y = (resolution.height - shellRect.height) / 2;
			splash.setLocation(x, y);
			
			shellRect = splashLabel.getBounds();
			progressBar.setBounds (5, shellRect.height, shellRect.width, 15);
			
			loadLabel.setLocation(5, shellRect.height + 20);
			
			splash.open();
	
			loadLabel.setText("Now loading...");
			
//			clearAllActionErrorLOG();
			
			createMenu();
	
			for (int i = 0; i <= progressBar.getMaximum()+30; i++) {
				try {
					Thread.sleep(20);
				} catch (Throwable th) {}
				
				progressBar.setSelection(i);
			}
	
			loadLabel.setText("Completed.");
			try {
				Thread.sleep(100);
			} catch (Throwable th) {
				throw new FatalException(th.getMessage());
			}
			
		} catch (FatalException e) {
			throw e;
		}
	}

	/**
	 * Clear all rows in table ACTIONLOG
	 *
	 */
//	private void clearAllActionErrorLOG() throws FatalException {
//
//		try {
//			BaseForm form = new BaseForm();
//			form.setActionForm("baseForm");
//			form.setActionMethod("clearLog");
//			
//			form = (BaseForm)Requester.execute(form);
//			
//			
//		} catch (FatalException e) {
//			MsgBoxUtils.fatalErrorMsgBox();
//			e.printStackTrace();
//			throw e;
//		}
//	}

	/**
	 * closeSplashWindow
	 */
	private void closeSplashWindow() {

		splash.dispose();
	}

	/**
	 * createMenu
	 * @throws FatalException
	 */
	@SuppressWarnings("unchecked")
	private void createMenu() throws FatalException {

		LoginDTO user = LoginDTO.getInstance();
		clblUser.setText(user.getName());
		
		log.info("get menu info start...");
		ArrayList menulist = null;
		BaseForm form = new BaseForm();
		try {
			form.setActionForm("baseForm");
			form.setActionMethod("getMenu");
			form.setUserDTO(user);
			
			form = (BaseForm)Requester.execute(form);
			
		} catch (SessionTimeOutException e) {
			log.warn("SessionTimeOutException.", e.getCause());
			form = (BaseForm)Requester.execute(form);
			
		} catch (FatalException e) {
			MsgBoxUtils.fatalErrorMsgBox();
			e.printStackTrace();
			throw e;
		}
		
		menulist = form.getMenu();
		
		if (null == menulist || menulist.isEmpty()){
			try {
				MsgBoxUtils.warningMsgBox("errors.MENU_NOT_REGISTERED");
				clblLine2.setVisible(false);
				btnExit.setFocus();
				return;
				
			} catch (ClientException e) {
				e.printStackTrace();
				throw e;
			}
		}

		clblLine2.setVisible(true);
		
		bar = new ExpandBar(comp_LEFT, SWT.V_SCROLL);
		bar.setBounds(0, 142, 197, comp_LEFT.getSize().y-175);
		bar.setSpacing(3);
		bar.setForeground(SWTResourceManager.getColor(232, 255, 251));
		
		bars = new ExpandItem[menulist.size()];
		
		ArrayList prgList = new ArrayList();
		for (int i = 0; i < menulist.size(); i++) {
			
			final Composite comp = new Composite(bar, SWT.NONE);
			GridLayout layout = new GridLayout();
		    layout.marginLeft = layout.marginTop = layout.marginRight = layout.marginBottom = 0;
		    layout.verticalSpacing = 3;
		    comp.setLayout(layout);
		    
		    MenuDTO menu = (MenuDTO)menulist.get(i);
		    ArrayList prgs = menu.getPrograms();
		    
	    	bars[i] = new ExpandItem(bar, SWT.V_SCROLL);
	    	bars[i].setText(LangResources.getText(menu.getMenuNameProperty()));
			
			if (!prgs.isEmpty()){
				
				int dispCount = 0;
		    	for (int j = 0; j < prgs.size(); j++) {
					final ProgramDTO prg = (ProgramDTO)prgs.get(j);
					
					if (!prg.getPrgAuth().equals(BaseConstant.NOT_DISP_AUTHOR)){
						final Label lblPrg = new Label(comp, SWT.NONE);
						if (LangResources.getCurrentLanguage().equals(BaseConstant.EN_LANG_FILE)){
							lblPrg.setText(prg.getEnName());
						}else{
							lblPrg.setText(prg.getVnName());
						}
						lblPrg.setCursor(SWTResourceManager.getCursor(SWT.CURSOR_HAND));
						lblPrg.setFont(BaseConstant.FONT_MENU);
						lblPrg.setForeground(BaseConstant.COLOR_MENU_MOUSE_MOVE);
						lblPrg.addMouseTrackListener(new MouseTrackAdapter() {
							Display display = Display.getCurrent();
							public void mouseEnter(MouseEvent e) {
								display.syncExec(new Runnable() {
									public void run() {
										lblPrg.setForeground(BaseConstant.COLOR_MENU_MOUSE_ENTER);
									}
								});

							}
							public void mouseExit(MouseEvent arg0) {
								display.syncExec(new Runnable() {
									public void run() {
										lblPrg.setForeground(BaseConstant.COLOR_MENU_MOUSE_MOVE);
									}
								});
							}
						});
						lblPrg.addMouseListener(new MouseAdapter() {

							public void mouseDown(MouseEvent arg0) {
								
								businessStart(prg);
							}
							
						});
						dispCount++;
						prgList.add(prg);
					}
				}
		    	
		    	if (dispCount > 0){
		    		bars[i].setExpanded(true);
		    	} else {
		    		bars[i].setExpanded(false);
		    	}
		    	
		    }else{
		    	bars[i].setExpanded(false);
		    }
		    bars[i].setHeight(comp.computeSize(SWT.DEFAULT, SWT.DEFAULT).y);
			bars[i].setControl(comp);
			bars[i].setData(menu);
			SWTManager.getInstance().setPrgList(prgList);
		}
		log.info("get menu info end.");
	}

	/**
	 * businessStart
	 * @param prg 
	 */
	protected void businessStart(ProgramDTO prg) {

		try{
			String prgname = "";
			if (LangResources.getCurrentLanguage().equals(BaseConstant.EN_LANG_FILE)){
				prgname = prg.getEnName();
			}else{
				prgname = prg.getVnName();
			}

			boolean res = authCheck(prg);
			if (res){

				Object args = new Object();

				callBusiness(prg, args, MENUOPEN);
				
			} else {
				MsgBoxUtils.errorMsgBox("errors.AUTHORITY", new Object[]{prgname});
			}
			
			
		} catch( Exception ex ){
//			log.error("SWTBase businessStart Exception.", ex);
			ex.printStackTrace();
			MsgBoxUtils.fatalErrorMsgBox();
		}
	}

	private boolean authCheck(ProgramDTO prg) {
		
		return true;
	}
	
	/**
	 * call business
	 * 
	 * @param prg
	 * @param argsObj
	 * @param openMode
	 * @throws Exception
	 */
	private boolean callBusiness(ProgramDTO prg, Object argsObj, int openMode) throws Exception {
		
		try {

			String prgname = "";
			if (LangResources.getCurrentLanguage().equals(BaseConstant.EN_LANG_FILE)) {
				prgname = prg.getEnName();
			} else {
				prgname = prg.getVnName();
			}

			log.info("*** Business start...");
			log.info("*** Program [" + prgname + "]");
			log.info("*** ClassID [" + prg.getPrgClass() + "]");

			final String TABOPEN = "1";
			final String SHELLOPEN = "2";

			if (prg.getPrgId() > 0) {

				String displayDivision = prg.getDspDivision();

				if (displayDivision == null) {
					log.error("Program register failed.");
					MsgBoxUtils.fatalErrorMsgBox();
					return false;
					
				} else if (displayDivision.equals(TABOPEN)) {

					if (openMode == MENUOPEN) {

						CTabItem item = createTabItem(prg.getPrgClass(), prgname);
						if (item != null && !this.shellP.isDisposed()) {
							tabFolder.setSelection(item);
						} else {
							return false;
						}

					} else if (openMode == BUSINESSOPEN) {

						CTabItem item = createTabItem(prg.getPrgClass(), prgname, argsObj);
						if (item != null && !this.shellP.isDisposed()) {
							tabFolder.setSelection(item);
						} else {
							return false;
						}

					}

				} else if (displayDivision.equals(SHELLOPEN)) {
					createShell(prg.getPrgClass());

				} else {
					log.error("Program register failed.");
					MsgBoxUtils.fatalErrorMsgBox();
					return false;
				}

			} else {
				log.error("Fatal system error.");
				throw new Exception("Fatal system error.");
			}

			return true;

		} catch (Exception e) {
			throw e;
		}
	}

	/**
	 * createTabItem
	 * 
	 */
	@SuppressWarnings("unchecked")
	private CTabItem createTabItem(String classID, final String prgName) throws Exception {

		final CTabItem tabItem = new CTabItem(tabFolder, SWT.NONE);
		tabItem.setText(prgName);

		Composite tabItemComposite = new Composite(tabFolder, SWT.NONE);

		Class[] constructorPramClass = new Class[3];
		constructorPramClass[0] = Composite.class;
		constructorPramClass[1] = Integer.TYPE;
		constructorPramClass[2] = String.class;

		Object[] constructorPram = new Object[3];
		constructorPram[0] = tabItemComposite;
		constructorPram[1] = new Integer(SWT.NONE);
		constructorPram[2] = prgName;

		Composite createdComposite = null;
		String classpath = createClassPath(classID);

		try {
			
			Class cls = Class.forName(classpath);
			Constructor clsConstructor = cls.getConstructor(constructorPramClass);

			createdComposite = (Composite) clsConstructor.newInstance(constructorPram);

			if (!shellP.isDisposed()) {
				
				createdComposite.setLocation(0, 0);
				
				cmpOnScrollComposite.setSize(createdComposite.getSize());
				
				compositeSetListener(createdComposite.getChildren());
				
				tabItem.setControl(tabItemComposite);
			}

		} catch (ClassNotFoundException ce) {
			log.error("ClassNotFoundException. ClassID = " + classpath);
			tabItemComposite.dispose();
			tabItem.dispose();
			throw ce;
			
		} catch (NoSuchMethodException ne) {
			log.error("NoSuchMethodException: " + ne);
			tabItemComposite.dispose();
			tabItem.dispose();
			throw ne;
			
		} catch (Exception e) {
			log.error("Exception. " + e);

			if (createdComposite != null) {
				createdComposite.dispose();
			}
			tabItemComposite.dispose();
			tabItem.dispose();
			throw e;
		}
		return tabItem;
	}

	/**
	 * create class path
	 * @param classID
	 * @return String
	 */
	private String createClassPath(String classID) {
		return BaseConstant.CLASS_ID_PREFIX + classID;
	}

	/**
	 * createTabItem
	 */
	@SuppressWarnings("unchecked")
	private CTabItem createTabItem(String classID, String menuName, Object argsObj) throws Exception {

		CTabItem tabItem = new CTabItem(tabFolder, SWT.NONE);
		tabItem.setText(menuName);

		Composite tabItemComposite = new Composite(tabFolder, SWT.NONE);

		Class[] constructorPramClass = new Class[3];
		constructorPramClass[0] = Composite.class;
		constructorPramClass[1] = Integer.TYPE;
		constructorPramClass[2] = Object.class;

		Object[] constructorPram = new Object[3];
		constructorPram[0] = tabItemComposite;
		constructorPram[1] = new Integer(SWT.NONE);
		constructorPram[2] = argsObj;

		Composite createdComposite = null;
		String classpath = createClassPath(classID);

		try {

			Class cls = Class.forName(classpath);
			Constructor clsConstructor = cls.getConstructor(constructorPramClass);
			createdComposite = (Composite) clsConstructor.newInstance(constructorPram);

			if (!shellP.isDisposed()) {
				
				createdComposite.setLocation(0, 0);
				
				cmpOnScrollComposite.setSize(createdComposite.getSize());
				
				compositeSetListener(createdComposite.getChildren());
				
				tabItem.setControl(tabItemComposite);
			}

		} catch (ClassNotFoundException ce) {
			log.error("ClassNotFoundException. ClassID = " + classpath);
			tabItemComposite.dispose();
			tabItem.dispose();
			throw ce;
			
		} catch (NoSuchMethodException ne) {
			log.error("NoSuchMethodException. " + ne);
			tabItemComposite.dispose();
			tabItem.dispose();
			throw ne;
			
		} catch (Exception e) {
			log.error("Exception. " + e);
			if (createdComposite != null) {
				createdComposite.dispose();
			}
			tabItemComposite.dispose();
			tabItem.dispose();
			throw e;
		}
		return tabItem;
	}

	/**
	 * createShell
	 */
	@SuppressWarnings("unchecked")
	private void createShell(String classID) throws Exception {

		Class[] constructorPramClass = new Class[1];
		constructorPramClass[0] = Shell.class;

		Object[] constructorPram = new Object[1];
		constructorPram[0] = shellP;

		Object createdShell = null;
		String classpath = createClassPath(classID);

		try {
			Class cls = Class.forName(classpath);
			Constructor clsConstructor = cls.getConstructor(constructorPramClass);
			createdShell = clsConstructor.newInstance(constructorPram);
			
		} catch (ClassNotFoundException ce) {
			log.error("ClassNotFoundException. ClassID = " + classpath);
			throw ce;
			
		} catch (NoSuchMethodException ne) {
			log.error("NoSuchMethodException." + ne);
			throw ne;
			
		} catch (Exception e) {
			log.error("Exception. " + e);
			if (createdShell != null) {
				((Shell) createdShell).dispose();
			}
			throw e;
		}
	}

	/**
	 * compositeSetListener
	 */
	private void compositeSetListener(Control[] children) {

		for (int i = 0; i < children.length; i++) {

			if (children[i] instanceof Text 
					|| children[i] instanceof Button
					|| children[i] instanceof Combo
					|| children[i] instanceof Table
					|| children[i] instanceof CCombo) {

				setControlKeyListener(children[i]);

			} else if (children[i] instanceof TabFolder
					|| children[i] instanceof CTabFolder) {

				setControlKeyListener(children[i]);
				Control[] grant = ((Composite) children[i]).getChildren();
				compositeSetListener(grant);

			} else if (children[i] instanceof Composite) {

				Control[] grant = ((Composite) children[i]).getChildren();
				compositeSetListener(grant);
			}
		}

	}

	/**
	 * setControlKeyListener
	 * @param control
	 */
	private void setControlKeyListener(Control control) {

		control.addKeyListener(new KeyAdapter() {
			public void keyPressed(KeyEvent e) {
				if (e.keyCode == 't' && e.stateMask == SWT.CTRL) {
					SWTBase baseForm = SWTManager.getInstance().getBaseManager();
					CTabItem currentItem = baseForm.tabFolder.getSelection();
					currentItem.setControl(currentItem.getControl());
				}
			}
		});

	}

	/**
	 * closeAction
	 * 
	 * @param tItem
	 * @return appName
	 * @throws FatalException
	 */
	private final boolean closeAction() {
		try {
			int tabSelectingIndex = tabFolder.getSelectionIndex();
			if (tabSelectingIndex < 0){
				exitAction(true);
				return true;
			}
			CTabItem tItem = tabFolder.getItem(tabSelectingIndex);
			String appName = tItem.getText();
			
		    int res = MsgBoxUtils.questionMsgBox("question.EXIT_PRG", new Object[] {appName});
		    if (res == SWT.YES) {
		    	tItem.dispose();
				SWTManager.getInstance().getTabFolder().setFocus();
				CTabItem currentItem =  SWTManager.getInstance().getSelectingTabItem();
				if (currentItem != null) {
					currentItem.setControl(currentItem.getControl());
				}else{
					cmpOnScrollComposite.setSize(COMPOSITE_SIZE_X, COMPOSITE_SIZE_Y);
					btnLogin.setFocus();
				}
				return true;
		    }
			
		}catch(ClientException e) {
			log.error("JNetComposite closeAction ClientException.", e);
		}
		return false;
	}

	/**
	 * disposeTab
	 * 
	 * @param tabIndex
	 */
	public void disposeTab(int tabIndex) {
		
		CTabItem[] items = tabFolder.getItems();
		Control[] controls = tabFolder.getChildren();
		items[tabIndex].dispose();
		controls[tabIndex].dispose();
		log.debug("Dispose Tab [" + tabIndex + "].");

		shellP.setActive();
	}
	
	/**
	 * dispose all tabs
	 *
	 */
	private void disposeAllTabs(){
		CTabItem[] tabitems = tabFolder.getItems();
		Control[] controls = tabFolder.getChildren();
		for (int i = 0; i < tabitems.length; i++) {
			tabitems[i].dispose();
			controls[i].dispose();
		}
		log.debug("Disposed all Tabs.");
		shellP.setActive();
	}

	/**
	 * exit app
	 * @param question 
	 */
	public void exitAction(boolean question) {

		try {
			if (question){
				int res = MsgBoxUtils.questionMsgBox("question.EXIT_APP");
				if (res == SWT.YES){
					Display display = shellP.getDisplay();
					Shell[] shells = display.getShells();
					for (int i = 0; i < shells.length; i++) {
						shells[i].dispose();
					}
					
				}else{
					btnExit.setFocus();
					return;
				}
				
			} else {
				Display display = shellP.getDisplay();
				Shell[] shells = display.getShells();
				for (int i = 0; i < shells.length; i++) {
					shells[i].dispose();
				}
			}
			
			LoginForm loginForm = new LoginForm();
			loginForm.setActionForm("loginForm");
			loginForm.setActionMethod("logoutAction");
			
			Requester.execute(loginForm);
			
		}catch (FatalException e) {
			log.error("SWTBase exitAction FatalException.", e);
			e.printStackTrace();
		}
	}
	
	/**
	 * relogin
	 */
	private void reloginAction() {

		try {
			int res = MsgBoxUtils.questionMsgBox("question.BE_SURE");
			if (res == SWT.NO){
				btnLogin.setFocus();
				return;
			}
			
		} catch (Exception e) {
			log.error("ClientException.", e);
			e.printStackTrace();
			return;
		}
		
		LoginForm loginForm = new LoginForm();
		loginForm.setSessionTimeout(false);
		loginForm.setUserDTO(LoginDTO.getInstance());
		SWTRelogin reLogin = new SWTRelogin(shellP);
		reLogin.setSearchCriteria(loginForm);
		
		if (loginForm.isUserChanged()){
			LoginDTO user = LoginDTO.getInstance();
			clblUser.setText(user.getName());
			clearMenu();
			try {
				createMenu();
				
			} catch (FatalException e) {
				return;
			}
			//dispose all tab
			disposeAllTabs();
		}
	}
	
	/**
	 * clear all menu item
	 *
	 */
	private void clearMenu() {

		if (null != bar && !bar.isDisposed()){
			Control[] baritms = bar.getChildren();
			for (int i = 0; i < baritms.length; i++) {
				baritms[i].dispose();
			}
			bar.dispose();
		}
	}
}